import json
import os
import requests
from typing import Dict, List, Optional
from dotenv import load_dotenv

# 加载配置
load_dotenv('.env')

STAR_FILE = os.getenv('STAR_FILE', 'starred_repos.json')
OUTPUT_FILE = os.getenv('OUTPUT_FILE', 'result.json')
DEEPSEEK_API_URL = os.getenv('DEEPSEEK_API_URL', 'https://api.deepseek.com/v1/chat/completions')
DEEPSEEK_API_KEY = os.getenv('DEEPSEEK_API_KEY')

# 提示词模板
PROMPT_TEMPLATE = """
请根据输入的 GitHub 仓库地址，分析仓库的主要功能，并提取其他关键信息。
请严格按照以下 JSON 格式输出，不要包含任何其他解释性文字：

{{
  "link": "仓库地址",
  "category": "技术分类",
  "summary": "代码仓库的主要功能介绍"
}}

技术分类必须从以下选项中选择：[Web开发, 移动端开发, 嵌入式系统, 操作系统, 网络技术, 网络安全, 数据库, 人工智能（AI）, 大数据, 云计算, DevOps, 游戏开发, 区块链, 编程语言, 工具与实用程序, 开源书籍/教程, 桌面应用, 音视频处理, 自动化脚本, 开源硬件, 其他]

summary 使用中文，技术名词可以使用英文，100个汉字以内。

仓库地址: {repo_url}
仓库描述: {repo_description}
"""

def load_json_file(filename: str) -> List[Dict]:
    """加载 JSON 文件"""
    if not filename or not os.path.exists(filename):
        return []
    
    with open(filename, "r", encoding="utf-8") as f:
        return json.load(f)

def save_json_file(data: List[Dict], filename: str):
    """保存数据到 JSON 文件"""
    if not filename:
        raise ValueError("文件名不能为空")
    with open(filename, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)

def call_deepseek_api(repo_url: str, repo_description: str) -> Optional[Dict]:
    """调用 DeepSeek API 获取仓库分类和摘要"""
    if not DEEPSEEK_API_URL or not DEEPSEEK_API_KEY:
        print("错误: DEEPSEEK_API_URL 或 DEEPSEEK_API_KEY 未配置")
        return None
        
    prompt = PROMPT_TEMPLATE.format(
        repo_url=repo_url,
        repo_description=repo_description or "无描述"
    )
    
    headers = {
        "Authorization": f"Bearer {DEEPSEEK_API_KEY}",
        "Content-Type": "application/json"
    }
    
    payload = {
        "model": "deepseek-chat",  # 根据实际情况调整
        "messages": [
            {
                "role": "user",
                "content": prompt
            }
        ],
        "temperature": 0.7
    }
    
    try:
        response = requests.post(DEEPSEEK_API_URL, headers=headers, json=payload, timeout=30)
        response.raise_for_status()
        
        # 假设 API 返回的是包含 JSON 的字符串
        content = response.json()
        # 提取模型的实际回复内容
        reply = content["choices"][0]["message"]["content"]
        print('reply:', reply)
        
        # 解析回复中的 JSON
        result = json.loads(reply)
        return result
    
    except Exception as e:
        print(f"调用 DeepSeek API 出错: {e}")
        return None

def is_already_processed(repo: Dict) -> bool:
    """检查仓库是否已经处理过"""
    return "category" in repo and "summary" in repo

def process_repositories():
    """处理仓库数据"""
    # 加载输入数据
    repos = load_json_file(STAR_FILE)
    if not repos:
        print(f"没有找到输入文件 {STAR_FILE} 或文件为空")
        return
    
    # 加载已有的输出数据（如果有）
    processed_repos = load_json_file(OUTPUT_FILE)
    
    # 创建基于仓库ID的映射字典，用于去重
    repo_map = {}
    
    # 首先添加已处理的数据（以ID为键，确保唯一性）
    for repo in processed_repos:
        repo_map[repo["id"]] = repo
    
    # 处理新的仓库
    new_count = 0

    for repo in repos:
        repo_id = repo["id"]
        
        # 如果已经存在于映射中且已处理过，跳过
        if repo_id in repo_map and is_already_processed(repo_map[repo_id]):
            continue
        
        # 调用 DeepSeek API 获取分类和摘要
        print(f"正在处理仓库: {repo['name']}")
        result = call_deepseek_api(repo["url"], repo["description"])
        
        if result:
            # 合并原有数据和新获取的数据
            processed_repo = {
                **repo,
                "category": result["category"],
                "summary": result["summary"]
            }
            repo_map[repo_id] = processed_repo
            new_count += 1
        else:
            # API 调用失败，保留原始数据但不添加到结果中，避免重复
            print(f"API调用失败，跳过仓库: {repo['name']}")
            continue
        
        # 将映射转换为列表
        output_data = list(repo_map.values())
        # 保存结果
        save_json_file(output_data, OUTPUT_FILE)
        print(f"共计{len(repos)}个仓库，当前已处理 {new_count} 个，总共仓库总数 {len(output_data)} 个。")
    
    

if __name__ == "__main__":
    try:
        process_repositories()
    except KeyboardInterrupt:
        print("已退出")
